package usr;

import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import java.util.TreeSet;

import util.D;
import util.FileTool;
import util.MathTool;
import util.Pair;
import util.Link;
import core.Global.NetType;
import core.Network;
import feature.Betweenness;
import feature.Closeness;
import feature.Degree;
import feature.Path;


public class Delay {
	/*************************************************************
	 * public method
	 */
	/*************************************************************/
	public void run(){

		//Network net = new Network("../data/delayNet.txt", NetType.UNDIRECTED, NumberType.LONG);
		Network net = new Network("../data/20131.txt", NetType.UNDIRECTED);
		
		HashMap<Number, Double> nodesBetweenness = null;//节点的介数
		//PairEdge：表示链路的起点和终点，LinkedList<Number>:链路上的点
		Set<Link> links = null;
		Set<Number> nodesSet = net.getAllNodeId();//网络中所有的节点
		/*
		 * 求网络的最短路径
		 */
		Path sp = new Path();
		links = sp.netShortestPath(net);
		
		int num = 3;//测试的次数
		
		FileTool f = new FileTool();
		
		
		Link link = null;
		StringBuffer sb = new StringBuffer();
		for(int j = 0; j < num; j++){
			String desPath = "../data/delay/"+j+"/";
			/*
			 *  网络参数
			 */
			//度
			Degree d = new Degree(net);
			//度的最大值
			f.write(d.netDegreeMax()+"", desPath+"netDegreeMax.txt");
			//度分布率
			f.write(d.netDegreeDistributionRate(), desPath+"netDegreeDistributionRate.txt");
			
			//紧密度
			Closeness c = new Closeness(net);
			f.write(c.netCloseness(net), desPath+"netCloseness.txt");
			/*
			 * 求网络的介数
			 */
			Betweenness b = new Betweenness(net);
			nodesBetweenness = b.nodesBetweenness(net);
			D.p(nodesBetweenness.get(2));
			f.write(b.getNetBetweennessMaxId()+"\t"+b.getNetBetweennessMaxValue(), desPath+"netBetweennessMax.txt");
			//平均最短路径长度
			f.write(sp.netAvgPathLength(net)+"", desPath+"netAvgPathLength.txt");
			
			LinkedList<Number> linksEdges = null;
			
			// 网络延迟
			double delay = 0;
			double delayMax = 0;
			double delaySum = 0;
			for(Iterator linksIt = links.iterator(); linksIt.hasNext();){
				link =  (Link) linksIt.next();
				linksEdges = (LinkedList<Number>) link.getEdges();
				
				delaySum = 0;
				delayMax = 0;
				for(int i = 0; i < linksEdges.size()-1; i++){
					delay = net.getEdgeWeight(linksEdges.get(i), linksEdges.get(i+1));
					delaySum += delay;
					if(delay > delayMax){
						delayMax = delay;
					}
				}
				sb.append(linksEdges.getFirst()+"\t"+linksEdges.getLast()+"\t"+delaySum+"\t"+delayMax+"\r\n");
			}
			f.write(sb, desPath+"netDelay.txt");
			/*
			 * 节点介数相乘，赋予边
			 */
			/*
			 * 使用TreeSet保存边的关系
			 */
			TreeSet<Pair<Number,Double>> edges = new  TreeSet<Pair<Number,Double>>(
						new Comparator<Pair<Number,Double>>(){
	
							@Override
							public int compare(Pair<Number,Double> o1, Pair<Number,Double> o2) {
								// TODO Auto-generated method stub
								double temp1 = o1.getValue();
								//Double.parseDouble(o1.getValue());
								double temp2 = o2.getValue();
								if(temp1 > temp2){
									return 1;
								}else if(temp1 == temp2){
									return 0;
								}else{
									return -1;
								}
							}
							
						}
					); 
			Number preNodeId = null;
			Number postNodeId = null;
			//ArrayList<Number> nodesArr = nodesSet.toArray(nodeId);
			Pair<Number,Double> edge = null;
			Iterator<Number> it1 = null;
			Iterator<Number> it2 = null;
			for(it1 =nodesSet.iterator();it1.hasNext();){
				preNodeId = it1.next();
				for(it2 =nodesSet.iterator();it2.hasNext();){
					postNodeId = it2.next();
					if(net.isHasEdge(preNodeId, postNodeId)){
						if(MathTool.compare(preNodeId, postNodeId, Network.getNumberType())){
							edge = new Pair<Number,Double>(postNodeId, preNodeId, nodesBetweenness.get(preNodeId)*nodesBetweenness.get(postNodeId));
						}else{
							edge = new Pair<Number,Double>(preNodeId, postNodeId, nodesBetweenness.get(preNodeId)*nodesBetweenness.get(postNodeId));
						}
						edges.add(edge);
					}
				}
			}
			
			/*
			 * 删除一定比例的边
			 */
			float rate = (float) 0.1;//删边比例
			int count = (int) Math.floor(edges.size()*rate);//删除边的个数
			float edgeWeight = 0;//边的权重
			Set<Pair> delEdges = new HashSet<Pair>();//记录删出的边
			
			Iterator<Pair<Number,Double>> it3 = edges.iterator();
			for (int i = 0; i < count; i++) {
				edge = it3.next();
				preNodeId = edge.getL();
				postNodeId = edge.getR();
				edgeWeight = net.getEdgeWeight(preNodeId, postNodeId);
				net.deleteEdge(preNodeId, postNodeId);
				if(!net.isConnectedNet()){
					//删除此边，不再是一个连通的网络
					net.insertEdge(preNodeId, postNodeId, edgeWeight);
				}else{
					//it3.remove();//如果在删除此边还仍能保持网络的连通
					delEdges.add(edge);
				}
			}
			
			/*
			 * 对于涉及到边删除的网络重新选路 
			 */
			Set<Link> newLink = new HashSet<Link>();
			for(Iterator<Link> it = links.iterator(); it.hasNext();){
				//遍历所有的链路
				link = it.next();
				for(Iterator<Pair> iterator2 = delEdges.iterator(); it2.hasNext();){
					//遍历所有删除边
					edge = iterator2.next();
					preNodeId = edge.getL();
					postNodeId = edge.getR();
					if(link.getEdges().contains(preNodeId)){
						int i = link.getEdges().indexOf(preNodeId);
						if(link.getEdges().get(i+1).equals(postNodeId) ||link.getEdges().get(i-1).equals(postNodeId) ){
							newLink.add(sp.bothNodeShortestPath(net, preNodeId, postNodeId));
							it.remove();
							break;
						}
					}
				}
			}//for links
			links.addAll(newLink);
			
		}//for num
	}
	
	public void extractNet(){
		Network net = new Network("../data/20131.txt", NetType.UNDIRECTED);
		Set<Number> nodesSet = net.getAllNodeId();//网络中所有的节点
		HashMap<Number, Double> nodesBetweenness = null;//节点的介数
		FileTool f = new FileTool();
		
		
		for(int j = 0; j < 5; j++){
			/*
			 * 求网络的介数
			 */
			
			String desPath = "../data/delay/"+j+"/";
			Betweenness b = new Betweenness(net);
			nodesBetweenness = b.nodesBetweenness(net);
			//D.p(nodesBetweenness.get(2));
			//f.write(b.getNetBetweennessMaxId()+"\t"+b.getNetBetweennessMaxValue(), desPath+"netBetweennessMax.txt");
			/*
			 * 节点介数相乘，赋予边
			 */
			/*
			 * 使用TreeSet保存边的关系
			 */
			TreeSet<Pair<Number,Double>> edges = new  TreeSet<Pair<Number,Double>>(
						new Comparator<Pair<Number,Double>>(){

							@Override
							public int compare(Pair<Number,Double> o1, Pair<Number,Double> o2) {
								// TODO Auto-generated method stub
								double temp1 = o1.getValue();
								//Double.parseDouble(o1.getValue());
								double temp2 = o2.getValue();
								if(temp1 > temp2){
									return 1;
								}else if(temp1 == temp2){
									return 0;
								}else{
									return -1;
								}
							}
							
						}
					); 
			Number preNodeId = null;
			Number postNodeId = null;
			//ArrayList<Number> nodesArr = nodesSet.toArray(nodeId);
			Pair<Number,Double> edge = null;
			Iterator<Number> it1 = null;
			Iterator<Number> it2 = null;
			for(it1 =nodesSet.iterator();it1.hasNext();){
				preNodeId = it1.next();
				for(it2 =nodesSet.iterator();it2.hasNext();){
					postNodeId = it2.next();
					if(net.isHasEdge(preNodeId, postNodeId)){
						if(MathTool.compare(preNodeId, postNodeId, Network.getNumberType())){
							edge = new Pair<Number,Double>(postNodeId, preNodeId, nodesBetweenness.get(preNodeId)*nodesBetweenness.get(postNodeId));
						}else{
							edge = new Pair<Number,Double>(preNodeId, postNodeId, nodesBetweenness.get(preNodeId)*nodesBetweenness.get(postNodeId));
						}
						edges.add(edge);
					}
				}
			}
			
			/*
			 * 删除一定比例的边
			 */
			float rate = (float) 0.1;//删边比例
			int count = (int) Math.floor(edges.size()*rate);//删除边的个数
			float edgeWeight = 0;//边的权重
			Set<Pair> delEdges = new HashSet<Pair>();//记录删出的边
			
			Iterator<Pair<Number,Double>> it3 = edges.iterator();
			for (int i = 0; i < count; i++) {
				edge = it3.next();
				preNodeId = edge.getL();
				postNodeId = edge.getR();
				edgeWeight = net.getEdgeWeight(preNodeId, postNodeId);
				net.deleteEdge(preNodeId, postNodeId);
				if(!net.isConnectedNet()){
					//删除此边，不再是一个连通的网络
					net.insertEdge(preNodeId, postNodeId, edgeWeight);
				}else{
					//it3.remove();//如果在删除此边还仍能保持网络的连通
					delEdges.add(edge);
				}
			}
			f.write(net.traverseEdge(), desPath+"net-"+j+".txt");
		}

	}
	/*************************************************************
	 * 
	 */
	/*************************************************************/

	
	/*************************************************************
	 * main
	 */
	/*************************************************************/
	public static void main(String[] args){
		Delay d = new Delay();
		d.extractNet();
	}
}
